package com.caipos.service;

import com.caipos.entity.Device;
import com.caipos.entity.DeviceCommand;
import com.caipos.netty.UdpServer;
import com.caipos.repository.jpa.DeviceCommandJpaRepository;
import com.caipos.repository.redis.DeviceCommandRedisRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

@Service
@RequiredArgsConstructor
public class DeviceCommandService {

    private final DeviceCommandJpaRepository commandJpaRepository;
    private final DeviceCommandRedisRepository commandRedisRepository;
    private final DeviceService deviceService;
    private final UdpServer udpServer;

    /**
     * 创建设备命令
     */
    @Transactional
    public DeviceCommand createCommand(DeviceCommand command) {
        // 1. 先从数据库获取最新版本的实体
        DeviceCommand latest = commandJpaRepository.findById(command.getId())
                .orElseThrow(() -> new RuntimeException("未找到命令"));

        // 2. 只更新需要修改的字段（保持最新的version）
        latest.setStatus(command.getStatus());

        // 3. 保存最新实体
        DeviceCommand savedCommand = commandJpaRepository.save(latest);

        // 检查设备是否存在
        if (!deviceService.deviceExists(command.getDeviceId())) {
            throw new IllegalArgumentException("Device with ID " + command.getDeviceId() + " does not exist");
        }

        // 立即发送命令（如果发送逻辑耗时较长，建议异步处理）
        sendCommand(savedCommand.getId());

        return savedCommand;
    }

    // 新增异步方法专门处理 Redis 缓存更新
    @Async
    public void updateRedisCache(DeviceCommand command) {
        commandRedisRepository.save(command);
    }

    /**
     * 发送命令到设备
     */
    @Transactional
    public boolean sendCommand(Long commandId) {
        Optional<DeviceCommand> commandOpt = commandJpaRepository.findById(commandId);
        if (commandOpt.isEmpty()) {
            return false;
        }
        
        DeviceCommand command = commandOpt.get();
        
        // 检查设备是否在线
        Optional<Device> deviceOpt = deviceService.getDeviceByDeviceId(command.getDeviceId());
        if (deviceOpt.isEmpty() || !"ONLINE".equals(deviceOpt.get().getStatus())) {
            return false;
        }
        
        Device device = deviceOpt.get();
        
        // 通过UDP服务器发送命令
        boolean sent = udpServer.sendCommandToDevice(
                device.getIpAddress(), 
                device.getPort(), 
                command
        );
        
        if (sent) {
            command.setStatus("SENT");
            command.setSendTime(LocalDateTime.now());
            DeviceCommand updatedCommand = commandJpaRepository.save(command);
            // 异步更新缓存，避免阻塞当前事务
            updateRedisCache(updatedCommand);

        }
        
        return sent;
    }

    /**
     * 更新命令执行状态
     */
    @Transactional
    public void updateCommandStatus(Long commandId, String status) {
        commandJpaRepository.findById(commandId).ifPresent(command -> {
            command.setStatus(status);
            if ("EXECUTED".equals(status)) {
                command.setExecuteTime(LocalDateTime.now());
            }
            commandJpaRepository.save(command);
            commandRedisRepository.save(command);
        });
    }

    /**
     * 获取设备的待处理命令
     */
    public List<DeviceCommand> getPendingCommands(String deviceId) {
        return commandJpaRepository.findByDeviceIdAndStatusOrderByCreateTimeDesc(deviceId, "PENDING");
    }

    /**
     * 获取所有待处理命令
     */
    public List<DeviceCommand> getAllPendingCommands() {
        return commandJpaRepository.findByStatusOrderByCreateTimeDesc("PENDING");
    }
}
    